import os.path
import SCons

SConsignFile()


# OPTIONS ######################################################################

opts = Options('dcsharp.conf');

opts.Add(PathOption('PREFIX', 'System base prefix path', '/usr'));
opts.Add(PathOption('LIBDIR', 'System library path', '$PREFIX/lib'));
opts.Add(PathOption('BINDIR', 'System executable path', '$PREFIX/bin'));
opts.Add(PathOption('SHAREDIR', 'System shared data path', '$PREFIX/share'));
opts.Add(PathOption('SYSCONFDIR', 'System configuration path', '/etc'));
opts.Add(PathOption('DESTDIR', 'System base installation path', '/'));

opts.Add(BoolOption('DEBUG', 'Compile with debug information', 0));
opts.Add(BoolOption('GNOME', 'Enable GNOME integration', 1));

# Builders from Diva

# MCS BUILDER ##################################################################

def mcsbuilder (source, target, env, for_signature, type):
	
	sourcesList = '';
	pkgList = '';
	refList = '';
	grefList = '';
	resList = '';
	
	# Create a list with all the sources
	for src in source:
		sourcesList += ' ' + str (src);

	# All the packages
	for pkg in env ['PKG']:
		pkgList += ' ' + '-pkg:%s' % (pkg);
	
	# All the references
	for ref in env ['REF']:
		if ref.startswith ('#'):
			refList += ' ' + '-r:%s' % (ref.strip ('#'));
		else:
			refList += ' ' + '-r:${TARGET.dir}/%s' % (ref);
	
	# All the global references
	for gref in env ['GREF']:
		grefList += ' ' + '-r:%s' % (gref);
 
	# All the resources
	for res in env ['RESOURCE']:
		if res.startswith ('#'):
			resList += ' ' + '-resource:%s' % (res.strip ('#'));
		else:
			resList += ' ' + '-resource:${TARGET.dir}/%s' % (res);

	# Return the prepared string
	cmd = 'gmcs ';
	
	if env ['DEBUG'] :
		cmd += '-debug -define:DEBUG';
	
	# All the extra flags
	for flag in env ['CSCFLAGS'] :
		cmd += ' ' + flag;
	
	cmd += '%s %s %s %s %s -out:%s -target:%s' % \
	       (pkgList, refList, sourcesList, resList, grefList, str(target[0]), type);

	return cmd;
	
def mcslibrary_action (source, target, env, for_signature):
	return mcsbuilder (source, target, env, for_signature, 'library');
	
def mcsexe_action (source, target, env, for_signature):
	return mcsbuilder (source, target, env, for_signature, 'exe');

def mcswinexe_action (source, target, env, for_signature):
	return mcsbuilder (source, target, env, for_signature, 'winexe');

# MCS DEP SCANNER ##############################################################

def mcs_scanner (node, env, path):
	
	# Scan all the refs
	path = env.GetLaunchDir ();
	depList = Split ('');
	for ref in env ['REF']:
		if ref.startswith ('#'):
			depList.append ('%s/%s' % (path, ref.strip ('#')));
		else:
			depList.append ('%s' % ref);

	# Scan all the resources
	resList = Split ('');
	for res in env ['RESOURCE']:
		if res.startswith ('#'):
			depList.append ('%s/%s' % (path, res.strip ('#')));
		else:
			depList.append ('%s' % res);
	return depList;


# MCS EMITTER ##################################################################

def mcs_emitter (target, source, env):
	
	# Add the debug target
	if env ['DEBUG'] :
		target.append (str (target[0]) + '.mdb');
		 
	return target, source;


# PKGCONFIG ####################################################################
# http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/UsingPkgConfig

def CheckPKGConfig(context, version):
	context.Message( 'Checking for pkg-config... ' )
	ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
	context.Result( ret )
	return ret

def CheckPKG(context, name):
	context.Message( 'Checking for %s... ' % name )
	ret = context.TryAction('pkg-config --exists \'%s\'' % name)[0]
	context.Result( ret )
	return ret


# ENV PARSE ####################################################################

def get_env(env):
	return {
		"PREFIX" : env.subst(env['PREFIX']),
		"BINDIR" : env.subst(env['BINDIR']),
		"LIBDIR" : env.subst(env['LIBDIR']),
		"SHAREDIR" : env.subst(env['SHAREDIR']),
		"DESTDIR" : env.subst(env['DESTDIR'])
	}

def parse_env(target, source, env):
	env_defines = get_env(env);
	
	for a_target, a_source in zip(target, source):
		file_out = file(str(a_target), "w");
		file_in = file(str(a_source), "r");
		file_out.write(file_in.read() % env_defines);
		file_in.close();
		file_out.close();
		
		# Copy permissions
		os.chmod(str(a_target), os.stat(str(a_source)).st_mode);


# ENV ##########################################################################

mcsScanner = Scanner(function = mcs_scanner);

mcsDll = Builder(generator = mcslibrary_action, target_scanner = mcsScanner,
	emitter = mcs_emitter);

mcsExe = Builder(generator = mcsexe_action, target_scanner = mcsScanner,
	emitter = mcs_emitter);

mcsWinExe = Builder(generator = mcswinexe_action, target_scanner = mcsScanner,
	emitter = mcs_emitter);

def generateMonoEnv(env):
	env['BUILDERS']['CLIProgram'] = mcsWinExe
	env['BUILDERS']['CLIConsoleProgram'] = mcsExe
	env['BUILDERS']['CLILibrary'] = mcsDll
	
	env['PKG']      = Split('')
	env['REF']      = Split('')
	env['GREF']     = Split('')
	env['RESOURCE'] = Split('')
	env['CSCFLAGS'] = Split('')

env = Environment(options = opts)
conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
                                       'CheckPKG' : CheckPKG })
Help(opts.GenerateHelpText(env))

generateMonoEnv(env)


# CONFIGURATION ################################################################

if not env.GetOption('clean'):
	opts.Save('dcsharp.conf', env);
	
	if not conf.CheckPKGConfig('0.15.0'):
		print 'pkg-config >= 0.15.0 not found.'
		Exit(1)
	
# Not cheching for mono, checking for gtk-sharp should be enough.
#
#	if not conf.CheckPKG('mono >= 1.1'):
#		print 'mono >= 1.1 not found.'
#		Exit(1)


# TARGETS AND PERMISSIONS ######################################################
# http://www.scons.org/wiki/InstallTargets

from SCons.Script.SConscript import SConsEnvironment
SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
	lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))

def InstallPerm(env, dest, files, perm):
	obj = env.Install(dest, files)
	for i in obj:
		env.AddPostAction(i, env.Chmod(str(i), perm))
	return dest

SConsEnvironment.InstallPerm = InstallPerm

# Define wrappers
SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
SConsEnvironment.InstallLibrary = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
SConsEnvironment.InstallData = lambda env, dest, files: InstallPerm(env, dest, files, 0644)

try:
	umask = os.umask(022)
	print 'Setting umask to 022 (was 0%o)' % umask
except OSError: # ignore on systems that don't support umask
	pass


# BUILD ########################################################################

Export('env')
Export('conf')
Export('parse_env')

SConscript('bin/SConscript')
SConscript('lib/SConscript')
SConscript('base/SConscript')
SConscript('gtk/SConscript')
